package com.xr.activiti;

import com.xr.activiti.pojo.Evection;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricActivityInstanceQuery;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipInputStream;

public class ActivitiDemo
{

    @Test
    public void deleteAllProcessDefinition()
    {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        DeploymentQuery deploymentQuery = repositoryService.createDeploymentQuery();
        List<Deployment> list = deploymentQuery.list();
        for (Deployment deployment : list)
        {
            repositoryService.deleteDeployment(deployment.getId(),true);
        }
    }


    @Test
    public void deploymentTest()
    {
        //  1.创建ProcessEngine
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        //  2.获取repositoryService
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
        //  3.使用该service进行流程部署，定义一个流程名字，把bpmn和png部署到数据中
        Deployment deployment = repositoryService.createDeployment().name("出差申请流程")
                .addClasspathResource("bpmn/evection.bpmn")
                .addClasspathResource("bpmn/evection.png")
                .deploy();
        //  4.输出部署信息
        System.out.println("流程部署id:"+deployment.getId());
        System.out.println("流程部署名字:"+deployment.getName());
    }

    @Test
    public void startProcessTest()
    {
        //  1.创建processEngine
        //  2.获取RunTimeService
        //  3.根据流程定义id启动流程
        //  4.获取输出内容
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RuntimeService runtimeService = defaultProcessEngine.getRuntimeService();

        HashMap<String, Object> assigneeMap = new HashMap<>();
        //  这个会先于MyTaskListener生效
        assigneeMap.put("assignee2","王总经理");
        assigneeMap.put("assignee3","赵财务");

        ProcessInstance evection = runtimeService.
                startProcessInstanceByKey("evection-uel","10001",assigneeMap);
        System.out.println("流程定义id：" + evection.getProcessDefinitionId());
        System.out.println("流程实例id：" + evection.getId());
        System.out.println("当前活动Id：" + evection.getActivityId());
    }


    /**
     * 查询当前个人待执行的任务
     */
    @Test
    public void testFindPersonalTaskList()
    {
        // 获取流程引擎、获取taskService、根据流程的key和任务负责人查询任务、输出
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery().processDefinitionKey("evection") // 流程的key
                .taskAssignee("zhangsan") // 负责人
                .list();

        for (Task task : taskList)
        {
            System.out.println("流程实例id：" + task.getProcessInstanceId());
            System.out.println("任务id：" + task.getId());
            System.out.println("任务负责人：" + task.getAssignee());
            System.out.println("任务名称：" + task.getName());
        }
    }

    @Test
    public void completeTask()
    {
        //  获取流程引擎、获取taskService、根据任务id完成任务
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery().processDefinitionKey("evection-parallel").
                taskAssignee("jack").singleResult();

        Evection evection = new Evection();
//        设置天数
        evection.setNum(10d);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("evection",evection);
        taskService.complete(task.getId(),hashMap);
    }

    @Test
    public void deploymentByZip()
    {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = processEngine.getRepositoryService();

        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/bpmn.zip");

        assert inputStream != null;
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        Deployment deploy = repositoryService.createDeployment()
                .name("出差申请表")
                .addZipInputStream(zipInputStream)
                .deploy();

        System.out.println(deploy.getId());
        System.out.println(deploy.getName());
    }

    /**
     * 查询流程定义
     */
    @Test
    public String queryProcessDefinition(String definitionKey)
    {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> definitionList = processDefinitionQuery.processDefinitionKey(definitionKey)
                .orderByProcessDefinitionVersion()
                .desc().list();
        for (ProcessDefinition processDefinition : definitionList)
        {
            System.out.println("流程定义 id="+processDefinition.getId());
            System.out.println("流程定义 name="+processDefinition.getName());
            System.out.println("流程定义 key="+processDefinition.getKey());
            System.out.println("流程定义 Version="+processDefinition.getVersion());
            System.out.println("流程部署ID ="+processDefinition.getDeploymentId());
        }
        return definitionList.get(0).getId();
    }

    /**
     * 删除流程定义
     * 说明：
     *
     * 1)       使用repositoryService删除流程定义，历史表信息不会被删除
     *
     * 2)       如果该流程定义下没有正在运行的流程，则可以用普通删除。
     *
     * 如果该流程定义下存在已经运行的流程，使用普通删除报错，可用级联删除方法将流程及相关记录全部删除。
     *
     * 先删除没有完成流程节点，最后就可以完全删除流程定义信息
     *
     * 项目开发中级联删除操作一般只开放给超级管理员使用.
     */
    @Test
    public void deleteProcessDefinition()
    {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
//        List<ProcessDefinition> evection = processDefinitionQuery.processDefinitionKey("evection")
//                .orderByProcessDefinitionVersion().desc().list();
//        ProcessDefinition processDefinition = evection.get(0);
//        repositoryService.deleteDeployment("17501");

        //  如果当前有流程并没有完成，需要级联删除
        repositoryService.deleteDeployment("37501",true);
    }

    @Test
    public void getDeploymentResource()
    {
        ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
        RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey("evection").singleResult();
        //  获取流程定义表里面的bpmn和png资源
        String resourceName = processDefinition.getResourceName();
        String diagramResourceName = processDefinition.getDiagramResourceName();

        //  获取bpmn和png资源的流
        InputStream bpmnInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        InputStream pngInputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName);

        //  构造outPutStream流
        File bpmnFile = new File("C:\\Users\\86180\\Desktop\\resource\\evection.bpmn");
        File pngFile = new File("C:\\Users\\86180\\Desktop\\resource\\evection.png");

        FileOutputStream bpmnOutputStream = null;
        FileOutputStream pngOutputStream = null;
        try {
            bpmnOutputStream = new FileOutputStream(bpmnFile);
            pngOutputStream = new FileOutputStream(pngFile);

            //  使用common-io的依赖工具类转换输入输出流
            IOUtils.copy(bpmnInputStream,bpmnOutputStream);
            IOUtils.copy(pngInputStream,pngOutputStream);

            //  关闭流
            bpmnOutputStream.close();
            pngOutputStream.close();
            pngInputStream.close();
            bpmnInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查看历史信息
     */
    @Test
    public void findHistoryInfo()
    {
//      获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//        获取HistoryService
        HistoryService historyService = processEngine.getHistoryService();
//        获取 actinst表的查询对象
        HistoricActivityInstanceQuery instanceQuery = historyService.createHistoricActivityInstanceQuery();
//        查询 actinst表，条件：根据 InstanceId 查询
//        instanceQuery.processInstanceId("2501");
//        查询 actinst表，条件：根据 DefinitionId 查询
        instanceQuery.processDefinitionId(queryProcessDefinition("evection"));
//        增加排序操作,orderByHistoricActivityInstanceStartTime 根据开始时间排序 asc 升序
        instanceQuery.orderByHistoricActivityInstanceStartTime().asc();
//        查询所有内容
        List<HistoricActivityInstance> activityInstanceList = instanceQuery.list();
//        输出
        for (HistoricActivityInstance hi : activityInstanceList) {
            System.out.println(hi.getActivityId());
            System.out.println(hi.getActivityName());
            System.out.println(hi.getProcessDefinitionId());
            System.out.println(hi.getProcessInstanceId());
            System.out.println("<==========================>");
        }
    }
}
